#include "VSMorphMainFunction.h"
#include "VSSwitchNode.h"
#include "VSGeometryNode.h"
#include "VSGeometry.h"
#include "VSMorphFunction.h"
#include "VSGraphicInclude.h"
using namespace VSEngine2;
IMPLEMENT_RTTI(VSMorphMainFunction,VSMorphBaseFunction)
static bool gs_bStreamRegistered_VSMorphMainFunction= VSMorphMainFunction::RegisterMainFactory();
bool VSMorphMainFunction::ms_bRegisterMainFactory = false;
bool VSMorphMainFunction::RegisterMainFactory()
{
	if (!ms_bRegisterMainFactory)
	{ 
		VSMain::AddInitialFuntion(VSMorphMainFunction::InitialClassFactory); 
		ms_bRegisterMainFactory = true;
	} 
	return ms_bRegisterMainFactory;

}
bool VSMorphMainFunction::InitialClassFactory()
{
	ms_ClassFactory.AddElement(ms_Type.GetName(),FactoryFunc);

	return 1;
}
VSObject * VSMorphMainFunction::FactoryFunc()
{
	return VS_NEW VSMorphMainFunction;

}
VSMorphMainFunction::VSMorphMainFunction(const VSUsedName & ShowName,VSMorphTree * pMorphTree)
:VSMorphBaseFunction(ShowName,pMorphTree)
{
	VSString InputName = _T("Morph");
	VSInputNode * pInputNode = NULL;

	pInputNode = VS_NEW VSInputNode(VSPutNode::AVT_MORPH,InputName,this);
	VSMAC_ASSERT(pInputNode);
	m_pInput.AddElement(pInputNode);

}
VSMorphMainFunction::VSMorphMainFunction()
{

}
VSMorphMainFunction::~VSMorphMainFunction()
{

}
bool VSMorphMainFunction::UpdateEx(double dAppTime)
{
	if(!VSMorphBaseFunction::UpdateEx(dAppTime))
		return false;

	if(!m_pInput[0]->GetOutputLink())
	{
		return false;
	}
	VSMorphFunction *pMorphFunction = (VSMorphFunction *)m_pInput[0]->GetOutputLink()->GetOwner();
	if(!pMorphFunction)
	{
		return false;
	}
	if(!pMorphFunction->Update(dAppTime))
		return false;
	VSGeometryNode * pGeomeNode = NULL;
	VSModelMeshNode* pMeshNode = (VSModelMeshNode *)m_pOwner->GetMeshNode();

	if (!pMeshNode)
	{
		return 0;
	}
	if (pMeshNode->GetLodType() == VSModelMeshNode::LT_DLOD)
	{
		if (pMeshNode->GetDlodNode())
		{
			pGeomeNode = DynamicCast<VSGeometryNode>(pMeshNode->GetDlodNode()->GetActiveNode());
		}
	}
	else
	{	
		pGeomeNode = DynamicCast<VSGeometryNode>(pMeshNode->GetChild(0));
	}
	if(!pGeomeNode)
		return false;


	//for all the geometry
	for (unsigned int i = 0 ; i < pGeomeNode->GetNodeNum() ; i++)
	{
		VSGeometry *  pGeome = (VSGeometry *)pGeomeNode->GetChild(i);
		if (pGeome)
		{
			VSMeshDate * pMeshDate = pGeome->GetMeshDate();
			if (!pMeshDate)
			{
				continue;
			}
			VSVertexBuffer * pVertexBuffer = pMeshDate->GetVertexBuffer();
			if (!pVertexBuffer)
			{
				continue;
			}

			if (pVertexBuffer->Lock())
			{
				continue;
			}

			//look for VRAM addr
			VSVector3 * pPosDest[VSMorphFunction::MAX_NUM_POS3] = {NULL};
			VSVector2 * pTexcoordDest[VSMorphFunction::MAX_NUM_TEXCOORD2] = {NULL};
			VSVector3 * pNormalDest[VSMorphFunction::MAX_NUM_NORMAL3] = {NULL};
			VSVector3 * pTangentDest = NULL;
			VSVector3 *	pBinormalDest = NULL;
			VSREAL		*pPSizeDest = NULL;
			VSColorRGBA	*pColorDest[VSMorphFunction::MAX_NUM_COLOR] = {NULL};
			VSVector3W	*pBlendWeightDest = NULL;
			VSVector3W	*pBlendIndexDest = NULL;
			for (unsigned int uiLevel = 0 ; uiLevel < VSMorphFunction::MAX_NUM_POS3 ; uiLevel++)
			{
				 pPosDest[uiLevel] = (VSVector3 *)pVertexBuffer->GetLockPositionDate(uiLevel);
			}
			for (unsigned int uiLevel = 0 ; uiLevel < VSMorphFunction::MAX_NUM_TEXCOORD2 ; uiLevel++)
			{
				pTexcoordDest[uiLevel] = (VSVector2 *)pVertexBuffer->GetLockTexCoordDate(uiLevel);
			}
			for (unsigned int uiLevel = 0 ; uiLevel < VSMorphFunction::MAX_NUM_NORMAL3 ; uiLevel++)
			{
				pNormalDest[uiLevel] = (VSVector3 *)pVertexBuffer->GetLockNormalDate(uiLevel);
			}
			pTangentDest = (VSVector3 *)pVertexBuffer->GetLockTangentDate();
			pBinormalDest = (VSVector3 *)pVertexBuffer->GetLockBinormalDate();
			pPSizeDest = (VSREAL*)pVertexBuffer->GetLockPSizeDate();
			for (unsigned int uiLevel = 0 ; uiLevel < VSMorphFunction::MAX_NUM_COLOR ; uiLevel++)
			{
				pColorDest[uiLevel] = (VSColorRGBA *)pVertexBuffer->GetLockColorDate(uiLevel);
			}
			pBlendWeightDest = (VSVector3W *)pVertexBuffer->GetLockBlendWeightDate();
			pBlendIndexDest = (VSVector3W *)pVertexBuffer->GetLockBlendIndicesDate();

			//for all the vertex , get result to VRAM
			unsigned int uiVertexNum = pGeome->GetVertexNum();
			for (unsigned int j = 0 ; j < uiVertexNum ; i++)
			{
				
				pMorphFunction->UpdateVertexDate(i,j);


				for (unsigned int uiLevel = 0 ; uiLevel < VSMorphFunction::MAX_NUM_POS3 ; uiLevel++)
				{
					
					VSVector3 * pVerSrc = pMorphFunction->GetPos(uiLevel);
					if (pPosDest[uiLevel] && pVerSrc)
					{
						*pPosDest[uiLevel] = *pVerSrc;
						
					}
					if (pPosDest[uiLevel])
					{
						pPosDest[uiLevel] =(VSVector3 *) (((unsigned char *)pPosDest[uiLevel]) + pVertexBuffer->GetOneVertexSize());
					}
				}
				
				for (unsigned int uiLevel = 0 ; uiLevel < VSMorphFunction::MAX_NUM_TEXCOORD2 ; uiLevel++)
				{
					VSVector2 * pTexcoordSrc = pMorphFunction->GetTexcoord(uiLevel);
					if (pTexcoordDest[uiLevel] && pTexcoordSrc)
					{
						*pTexcoordDest[uiLevel] = *pTexcoordSrc;
						
					}
					if (pTexcoordDest[uiLevel])
					{
						pTexcoordDest[uiLevel] =(VSVector2 *) (((unsigned char *)pTexcoordDest[uiLevel]) + pVertexBuffer->GetOneVertexSize());
					}
				}


				for (unsigned int uiLevel = 0 ; uiLevel < VSMorphFunction::MAX_NUM_NORMAL3 ; uiLevel++)
				{
					VSVector3 * pNormalSrc = pMorphFunction->GetNormal(uiLevel);
					if (pNormalDest[uiLevel] && pNormalSrc)
					{
						*pNormalDest[uiLevel] = *pNormalSrc;
						
					}
					if (pNormalDest[uiLevel])
					{
						pNormalDest[uiLevel] =(VSVector3 *) (((unsigned char *)pNormalDest[uiLevel]) + pVertexBuffer->GetOneVertexSize());
					}
				}

				VSVector3 * pTangentSrc = pMorphFunction->GetTangent();
				if (pTangentDest && pTangentSrc)
				{
					*pTangentDest = *pTangentSrc;
					
				}
				if (pTangentDest)
				{
					pTangentDest  =(VSVector3 *) (((unsigned char *)pTangentDest ) + pVertexBuffer->GetOneVertexSize());
				}

				VSVector3 * pBinormalSrc = pMorphFunction->GetBinormal();
				if (pBinormalDest && pBinormalSrc)
				{
					*pBinormalDest = *pBinormalSrc;
					
				}
				if (pBinormalDest)
				{
					pBinormalDest  =(VSVector3 *) (((unsigned char *)pBinormalDest ) + pVertexBuffer->GetOneVertexSize());
				}

				VSREAL * pPSizeSrc = pMorphFunction->GetPSize();
				if (pPSizeDest && pPSizeSrc)
				{
					*pPSizeDest = *pPSizeSrc;
					
				}
				if (pPSizeDest)
				{
					pPSizeDest  =(VSREAL *) (((unsigned char *)pPSizeDest ) + pVertexBuffer->GetOneVertexSize());
				}

				for (unsigned int uiLevel = 0 ; uiLevel < VSMorphFunction::MAX_NUM_COLOR ; uiLevel++)
				{
					VSColorRGBA * pColorSrc = pMorphFunction->GetColor(uiLevel);
					if (pColorDest[uiLevel] && pColorSrc)
					{
						*pColorDest[uiLevel] = *pColorSrc;
						
					}
					if (pColorDest[uiLevel])
					{
						pColorDest[uiLevel]  =(VSColorRGBA *) (((unsigned char *)pColorDest[uiLevel] ) + pVertexBuffer->GetOneVertexSize());
					}
				}

				VSVector3W * pBlendWeightSrc = pMorphFunction->GetBlendWeight();
				if (pBlendWeightDest && pBlendWeightSrc)
				{
					*pBlendWeightDest = *pBlendWeightSrc;
					
				}
				if (pBlendWeightDest)
				{
					pBlendWeightDest  =(VSVector3W *) (((unsigned char *)pBlendWeightDest ) + pVertexBuffer->GetOneVertexSize());
				}

				VSVector3W * pBlendIndexSrc = pMorphFunction->GetBlendIndex();
				if (pBlendIndexDest && pBlendIndexSrc)
				{
					*pBlendIndexDest = *pBlendIndexSrc;
					
				}
				if (pBlendIndexDest)
				{
					pBlendIndexDest  =(VSVector3W *) (((unsigned char *)pBlendIndexDest ) + pVertexBuffer->GetOneVertexSize());
				}
			}

			pVertexBuffer->UnLock();
		}
		
	}
	return true;

}
